home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 7 / Example 7.3 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  8.2 KB  |  301 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 7.3: Skinned Mesh Example                        //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include "debug.h"
  9. #include "skinnedMesh.h"
  10. #include "shader.h"
  11.  
  12. class APPLICATION
  13. {
  14.     public:
  15.         APPLICATION();
  16.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  17.         HRESULT Update(float deltaTime);
  18.         HRESULT Render();
  19.         HRESULT Cleanup();
  20.         HRESULT Quit();
  21.         DWORD FtoDword(float f){return *((DWORD*)&f);}
  22.  
  23.     private:
  24.         IDirect3DDevice9* m_pDevice; 
  25.         SKINNEDMESH m_skinnedMesh;
  26.  
  27.         bool m_wireframe, m_showSkeleton;
  28.         float m_angle, m_time;
  29.         std::vector<std::string> m_animations;
  30.         int m_activeAnimation;
  31.         HWND m_mainWindow;
  32.         ID3DXFont *m_pFont;
  33.  
  34.         //Shaders
  35.         SHADER m_unitVS, m_unitPS;
  36.         D3DXHANDLE m_worldHandle, m_viewProjHandle, m_sunHandle;
  37. };
  38.  
  39. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  40. {
  41.     APPLICATION app;
  42.  
  43.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  44.         return 0;
  45.  
  46.     MSG msg;
  47.     memset(&msg, 0, sizeof(MSG));
  48.     int startTime = timeGetTime(); 
  49.  
  50.     while(msg.message != WM_QUIT)
  51.     {
  52.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  53.         {
  54.             ::TranslateMessage(&msg);
  55.             ::DispatchMessage(&msg);
  56.         }
  57.         else
  58.         {    
  59.             int t = timeGetTime();
  60.             float deltaTime = (t - startTime)*0.001f;
  61.  
  62.             app.Update(deltaTime);
  63.             app.Render();
  64.  
  65.             startTime = t;
  66.         }
  67.     }
  68.  
  69.     app.Cleanup();
  70.  
  71.     return msg.wParam;
  72. }
  73.  
  74. APPLICATION::APPLICATION()
  75. {
  76.     m_pDevice = NULL; 
  77.     m_mainWindow = 0;
  78.     m_wireframe = m_showSkeleton = false;
  79.     srand(GetTickCount());
  80.     m_angle = m_time = 0.0f;
  81. }
  82.  
  83. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  84. {
  85.     debug.Print("Application initiated");
  86.  
  87.     //Create Window Class
  88.     WNDCLASS wc;
  89.     memset(&wc, 0, sizeof(WNDCLASS));
  90.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  91.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  92.     wc.hInstance     = hInstance;
  93.     wc.lpszClassName = "D3DWND";
  94.  
  95.     //Register Class and Create new Window
  96.     RegisterClass(&wc);
  97.     m_mainWindow = CreateWindow("D3DWND", "Example 7.3: Skinned Mesh Example", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  98.     SetCursor(NULL);
  99.     ShowWindow(m_mainWindow, SW_SHOW);
  100.     UpdateWindow(m_mainWindow);
  101.  
  102.     //Create IDirect3D9 Interface
  103.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  104.  
  105.     if(d3d9 == NULL)
  106.     {
  107.         debug.Print("Direct3DCreate9() - FAILED");
  108.         return E_FAIL;
  109.     }
  110.  
  111.     //Check that the Device supports what we need from it
  112.     D3DCAPS9 caps;
  113.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  114.  
  115.     //Hardware Vertex Processing or not?
  116.     int vp = 0;
  117.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  118.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  119.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  120.  
  121.     //Check vertex & pixelshader versions
  122.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  123.     {
  124.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  125.     }
  126.  
  127.     //Set D3DPRESENT_PARAMETERS
  128.     D3DPRESENT_PARAMETERS d3dpp;
  129.     d3dpp.BackBufferWidth            = width;
  130.     d3dpp.BackBufferHeight           = height;
  131.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  132.     d3dpp.BackBufferCount            = 1;
  133.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  134.     d3dpp.MultiSampleQuality         = 0;
  135.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  136.     d3dpp.hDeviceWindow              = m_mainWindow;
  137.     d3dpp.Windowed                   = windowed;
  138.     d3dpp.EnableAutoDepthStencil     = true; 
  139.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  140.     d3dpp.Flags                      = 0;
  141.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  142.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  143.  
  144.     //Create the IDirect3DDevice9
  145.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  146.                                  vp, &d3dpp, &m_pDevice)))
  147.     {
  148.         debug.Print("Failed to create IDirect3DDevice9");
  149.         return E_FAIL;
  150.     }
  151.  
  152.     //Release IDirect3D9 interface
  153.     d3d9->Release();
  154.  
  155.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  156.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  157.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  158.  
  159.     m_skinnedMesh.Load("mesh/drone.x", m_pDevice);    
  160.     m_animations = m_skinnedMesh.GetAnimations();
  161.     m_activeAnimation = m_animations.size() - 3;
  162.     m_skinnedMesh.SetAnimation((char*)m_animations[m_activeAnimation].c_str());
  163.  
  164.     //Set sampler state
  165.     for(int i=0;i<8;i++)
  166.     {
  167.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  168.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  169.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  170.     }
  171.  
  172.     //Setup shaders
  173.     m_unitVS.Init(m_pDevice, "shaders/lighting.vs", VERTEX_SHADER);
  174.     m_worldHandle = m_unitVS.GetConstant("matW");
  175.     m_viewProjHandle = m_unitVS.GetConstant("matVP");
  176.     m_sunHandle = m_unitVS.GetConstant("DirToSun");
  177.  
  178.     m_unitPS.Init(m_pDevice, "shaders/unit.ps", PIXEL_SHADER);
  179.  
  180.     return S_OK;
  181. }
  182.  
  183. HRESULT APPLICATION::Update(float deltaTime)
  184. {    
  185.     m_angle += deltaTime * 0.5f;
  186.     if(m_angle > D3DX_PI * 2.0f)
  187.         m_angle -= D3DX_PI * 2.0f;
  188.  
  189.     m_time = deltaTime * 0.5f;
  190.         
  191.     if(KEYDOWN('W'))
  192.     {
  193.         m_wireframe = !m_wireframe;
  194.         Sleep(300);
  195.     }
  196.     else if(KEYDOWN(VK_RETURN))
  197.     {
  198.         m_showSkeleton = !m_showSkeleton;
  199.         Sleep(300);
  200.     }
  201.     else if(KEYDOWN(VK_SPACE))
  202.     {
  203.         m_activeAnimation++;
  204.         if(m_activeAnimation >= m_animations.size())
  205.             m_activeAnimation = 0;
  206.  
  207.         m_skinnedMesh.SetAnimation((char*)m_animations[m_activeAnimation].c_str());
  208.         Sleep(300);
  209.     }
  210.     else if(KEYDOWN(VK_ESCAPE))
  211.     {
  212.         Quit();
  213.     }
  214.  
  215.     return S_OK;
  216. }    
  217.  
  218. HRESULT APPLICATION::Render()
  219. {
  220.     // Clear the viewport
  221.     m_pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  222.  
  223.     //Set camera
  224.     D3DXMATRIX view, proj, world;
  225.     D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 10.0f, -50.0f), &D3DXVECTOR3(0.0f, 4.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  226.     D3DXMatrixOrthoLH(&proj, 10.0f, 9.0f, 0.1f, 1000.0f);
  227.     
  228.     //Set Skeleton to rotate around the Y-axis
  229.     D3DXMATRIX r, s;
  230.     D3DXMatrixRotationYawPitchRoll(&r, m_angle, 0.0f, 0.0f);
  231.     D3DXMatrixScaling(&s, 1.2f, 1.2f, 1.2f);
  232.     world = s * r;
  233.     
  234.     m_pDevice->SetTransform(D3DTS_VIEW, &view);
  235.     m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);
  236.     m_pDevice->SetTransform(D3DTS_WORLD, &world);
  237.  
  238.     // Begin the scene 
  239.     if(SUCCEEDED(m_pDevice->BeginScene()))
  240.     {
  241.         if(m_wireframe)m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);    
  242.         else m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  243.  
  244.         m_unitVS.SetMatrix(m_worldHandle, world);
  245.         m_unitVS.SetMatrix(m_viewProjHandle, view * proj);
  246.  
  247.         D3DXVECTOR3 sun;
  248.         D3DXVec3Normalize(&sun, &D3DXVECTOR3(0.5f, 1.0f, -0.2));
  249.         m_unitVS.SetVector3(m_sunHandle, sun);
  250.  
  251.         m_unitVS.Begin();
  252.         m_unitPS.Begin();
  253.  
  254.         m_skinnedMesh.SetPose(world, NULL, m_time);
  255.         m_skinnedMesh.Render(NULL);
  256.  
  257.         m_unitPS.End();
  258.         m_unitVS.End();
  259.  
  260.         if(m_showSkeleton)
  261.         {
  262.             m_pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  263.             m_skinnedMesh.RenderSkeleton(NULL, NULL, world);
  264.         }
  265.  
  266.         RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}, {10, 90, 0, 0}};
  267.         m_pFont->DrawText(NULL, "Space: Change Animation", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  268.         m_pFont->DrawText(NULL, "Return: Show Skeleton On/Off", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  269.         m_pFont->DrawText(NULL, "W: Wireframe On/Off", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  270.  
  271.         std::string str = "Active Animation: " + m_animations[m_activeAnimation];
  272.         m_pFont->DrawText(NULL, str.c_str(), -1, &r[3], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  273.  
  274.         // End the scene.
  275.         m_pDevice->EndScene();
  276.         m_pDevice->Present(0, 0, 0, 0);
  277.     }
  278.  
  279.     return S_OK;
  280. }
  281.  
  282. HRESULT APPLICATION::Cleanup()
  283. {
  284.     try
  285.     {
  286.         m_pFont->Release();
  287.         m_pDevice->Release();
  288.  
  289.         debug.Print("Application terminated");
  290.     }
  291.     catch(...){}
  292.  
  293.     return S_OK;
  294. }
  295.  
  296. HRESULT APPLICATION::Quit()
  297. {
  298.     ::DestroyWindow(m_mainWindow);
  299.     ::PostQuitMessage(0);
  300.     return S_OK;
  301. }